﻿using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.IO;
using System.Linq;
using System.Text;
using Common;
using Model.Database;
using SearchModel;
using System.Web;
using IBll.Sys;
using Model.Sys.Config;

namespace Bll//此处最好为Bll，这样和Bll下的同名类进行合并而扩展
{
    public partial class UserInfoBll
    {
        /// <summary>
        /// 根据用户名和密码查询UserInfo
        /// </summary>
        /// <param name="username"></param>
        /// <param name="password"></param>
        /// <returns></returns>
        public UserInfo GetUserInfoByUsernamePassword(string username, string password)
        {
            //禁用此上下文的代理类功能（延迟加载），为了从MemoryCache中取缓存时，,不报"找不到以'EntityFrameworkDynamicProxies-'开头的程序集"的错误
            //CurrentDalSession.CurrentDbContext.Configuration.ProxyCreationEnabled = true;

            //带参数的sql查询单表全部属性
            //string strSql = "select * from UserInfo where loginname=@loginname and loginpassword=@loginpassword";
            //DbParameter[] dbParameter =
            //{
            //    new SqlParameter("@loginname",username),
            //    new SqlParameter("@loginpassword",password)
            //};
            //List<UserInfo> obj = CurrentDalSession.UserInfoDal.GetList(strSql, dbParameter);

            //sql多列查询(ViewModel筛选)
            //string strSql = "select A.loginname,A.loginpassword from UserInfo A where A.loginname='1'";
            //IList<ViewModel> obj = CurrentDalSession.BaseDalExtend.GetList<ViewModel>(strSql);
            //sql多列查询(ViewModel扩展，此处的UserInfo为扩展后的，有重复列名的，要自定义ViewModel)
            //string strSql = "select A.*,B.* from UserInfo A,Test B where A.loginname=B.name";
            //IList<ViewModel> obj = CurrentDalSession.BaseDalExtend.GetList<ViewModel>(strSql);

            //linq查询多表(匿名类法)
            //var linq = from A in CurrentDalSession.CurrentDbContext.UserInfo
            //           from B in CurrentDalSession.CurrentDbContext.Test
            //           where (A.LoginName == B.name)
            //           select new
            //           {
            //               UserInfo = A,
            //               Test = B,
            //           };
            //UserInfo userinfo = linq.ToList()[0].UserInfo;
            //Test test = linq.ToList()[0].Test;
            //linq查询多表(ViewMOdel法)
            //var linq = from A in CurrentDalSession.CurrentDbContext.UserInfo
            //           from B in CurrentDalSession.CurrentDbContext.Test
            //           where (A.LoginName == B.name)
            //           select new VMUserInfo
            //           {
            //               UserInfo = A,
            //               Test = B,
            //           };
            //IList<VMUserInfo> lstResult = CurrentDalSession.BaseDalExtend.GetList<VMUserInfo>(linq);

            UserInfo result = null;
            UserInfo userinfo = CurrentDal.GetEntity(a => a.LoginName == username && a.LoginPassword == password);
            
            if (userinfo != null) 
            {
                if (userinfo.IsSuper.HasValue && userinfo.IsSuper.Value) //超级管理员
                {
                    userinfo.Roles.Add(new Role() {RoleId = "1",RoleName = "超级管理员",Powers = CurrentDalSession.PowerDal.GetList()});//要加RoleId，不然跟新时，会报RoleId为null的错，即使更新UserInfo不涉及更新Role。
                    result = userinfo;
                }
                else
                {
                    result= CurrentDal
                        .GetIQueryable(a => a.LoginName == username && a.LoginPassword == password)
                        .Include("Roles.Powers")
                        .Include("Departments.Roles.Powers")
                        .FirstOrDefault();
                }
            }

            //返回前，开启代理类功能
            //CurrentDalSession.CurrentDbContext.Configuration.ProxyCreationEnabled = true;

            return result;
        }

        /// <summary>
        /// 条件分页查询
        /// </summary>
        /// <param name="pageIndex"></param>
        /// <param name="pageSize"></param>
        /// <param name="total"></param>
        /// <param name="smUserInfo"></param>
        /// <returns></returns>
        public List<UserInfo> GetListBySearchPage(int pageIndex,int pageSize,out int total, SMUserInfo smUserInfo)
        {
            IQueryable<UserInfo> userInfoIq= CurrentDal.GetIQueryable().Where(a=>!a.IsSuper.HasValue||a.IsSuper.Value==false);

            userInfoIq=BaseSearch(userInfoIq,smUserInfo);
            total=userInfoIq.Count();
            userInfoIq=userInfoIq.OrderByDescending(a => a.AddTime);
            userInfoIq=userInfoIq.Skip((pageIndex - 1)*pageSize).Take(pageSize);//分页前必须排序，不然EF报错

            return userInfoIq.ToList();
        }

        /// <summary>
        /// 批量删除
        /// </summary>
        /// <param name="idArr"></param>
        public void ListDelete(string[] idArr)
        {
            //try//此处留一个使用事务的书写格式，以供后期拷贝使用，这里的批量删除不需事务，因为只有一句sql，无需再套事务，注意：这里使用EF.Extended，sql语句无法监听，要通过Sqlserver Profiler监听
            //{
            //    CurrentDalSession.BaseDalExtend.BeginTrans();

                CurrentDal.Delete(a => idArr.Contains(a.UserInfoId));
                CurrentDalSession.SaveChanges();

            //    CurrentDalSession.BaseDalExtend.Commit();
            //}
            //catch (Exception ex)
            //{
            //    CurrentDalSession.BaseDalExtend.Rollback();
            //    throw new Exception(ex.Message);
            //}
            //finally
            //{
            //    CurrentDalSession.BaseDalExtend.DisposeTrans();
            //}
        }

        /// <summary>
        /// 获取角色
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public List<Role> GetRole(string id)
        {
            List<Role> roleList=new List<Role>();
            //传统的逻辑应该是这样：根据id然后查Role表，简单明了
            UserInfo userInfo=CurrentDal.GetIQueryable(a => a.UserInfoId == id).Include("Roles").FirstOrDefault();//这里多查询了一次UserInfo，可看出以后的表设计要尽可能避开物理关联，ef要禁用导航属性，用关联id来查询关联的集合，提高linq可读性。早起设计的几张表没注意到这点。
            
            if (userInfo.Roles.Count > 0)
            {
                roleList= userInfo.Roles.ToList();
            }

            return roleList;
        }

        /// <summary>
        /// 批量禁用（这里的实现方法使用了原生态的手写sql，效率方面并没有提高多少，只是比EF提供的方法少一次查询）
        /// </summary>
        public void ListForbidden(string[] idArr)
        {
            string sql = "update UserInfo set IsForbidden=1 where UserInfoId in (@idStr)";
            string idStr = null;
            StringBuilder idStrSB = new StringBuilder("");
            foreach (var id in idArr)
            {
                idStrSB.Append("'" + id + "'");
                idStrSB.Append(",");
            }
            idStr = idStrSB.ToString();
            idStr = StringHelper.DelLastChar(idStr, ",");
            sql = sql.Replace("@idStr", idStr);
            CurrentDalSession.BaseDalExtend.ExecuteSql(sql);
        }

        /// <summary>
        /// 批量解禁（这里的实现方法使用了原生态的手写sql，效率方面并没有提高多少，只是比EF提供的方法少一次查询）
        /// </summary>
        public void ListNoForbidden(string[] idArr)
        {
            string sql = "update UserInfo set IsForbidden=0 where UserInfoId in (@idStr)";
            string idStr = null;
            StringBuilder idStrSB = new StringBuilder("");
            foreach (var id in idArr)
            {
                idStrSB.Append("'" + id + "'");
                idStrSB.Append(",");
            }
            idStr = idStrSB.ToString();
            idStr = StringHelper.DelLastChar(idStr, ",");
            sql = sql.Replace("@idStr", idStr);
            CurrentDalSession.BaseDalExtend.ExecuteSql(sql);
        }

        /// <summary>
        /// 增加用户和UserInfo_Role关系表,UserInfo_Department关系表
        /// </summary>
        /// <param name="userInfo"></param>
        /// <returns></returns>
        public bool AddUserInfoAndUserInfo_Role_Department(UserInfo userInfo)
        {
            CurrentDal.Add(userInfo);
            CurrentDalSession.CurrentDbContext.ChangeTracker.DetectChanges();
            CurrentDalSession.SaveChanges();

            return true;
        }

        /// <summary>
        /// 更新用户和UserInfo_Role关系表,UserInfo_Department关系表
        /// </summary>
        /// <param name="userInfo"></param>
        /// <returns></returns>
        public bool UpdateUserInfoAndUserInfo_Role_Department(UserInfo userInfo)
        {
            CurrentDal.Update(userInfo);
            CurrentDalSession.CurrentDbContext.ChangeTracker.DetectChanges();
            CurrentDalSession.SaveChanges();
            
            return true;
        }

        /// <summary>
        /// 获取部门
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public List<Department> GetDepartment(string id)
        {
            List<Department> departmentList = new List<Department>();
            UserInfo userInfo =CurrentDal.GetIQueryable(a=>a.UserInfoId==id).Include("Departments").FirstOrDefault();

            if (userInfo.Departments.Count > 0)
            {
                departmentList = userInfo.Departments.ToList();
            }

            return departmentList;
        }

        /// <summary>
        /// 更新头像
        /// </summary>
        /// <param name="file"></param>
        /// <param name="loginUser"></param>
        public void UpdateHeadPhoto(HttpPostedFileBase file, UserInfo loginUser)
        {
            try
            {
                string folderpath = HttpContext.Current.Server.MapPath("/File/UploadFile/HeadPhoto/");//上传图片的文件夹
                string ext = Path.GetExtension(file.FileName);//扩展名
                string fileName = DateTime.Now.ToString("yyyyMMdd") + StringHelper.GetGuidString().Substring(0, 10) + ext;//文件名
                string filePath = "/File/UploadFile/HeadPhoto/" + fileName;//文件路径
                string filePhysicalPath = folderpath + fileName;//文件物理路径
                string cacheKey= CookieHelper.GetCookieValue(CookieConfig.UserInfoLoginCookieName);//缓存key

                if (!Directory.Exists(folderpath))
                {
                    Directory.CreateDirectory(folderpath);
                }
                file.SaveAs(filePhysicalPath);
                //删除之前的头像文件
                if (!string.IsNullOrEmpty(loginUser.Headphoto))
                {
                    string oldFilePhysicalPath = HttpContext.Current.Server.MapPath(loginUser.Headphoto);
                    File.Delete(oldFilePhysicalPath);
                }
                //更新
                loginUser.Headphoto = filePath;
                CurrentDal.Update(loginUser);
                CurrentDalSession.SaveChanges();
                //更新后同时更新缓存
                ICacheBll cacheBll = IocHelper.AutofacResolve<ICacheBll>();
                cacheBll.Update(cacheKey, loginUser);
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }



















        #region 私有方法
        private IQueryable<UserInfo> BaseSearch(IQueryable<UserInfo> userInfoIq, SMUserInfo smUserInfo)
        {
            if (!string.IsNullOrEmpty(smUserInfo.Nickname))
            {
                userInfoIq = userInfoIq.Where(a => a.Nickname.Contains(smUserInfo.Nickname));
            }
            if (smUserInfo.AddTime != null)
            {
                DateTime dateTimeStart = DateTime.Parse(smUserInfo.AddTime.Value.ToString("yyyy/MM/dd") + " 00:00:00");//Lambda不支持转换，要先转换好
                DateTime dateTimeEnd = DateTime.Parse(smUserInfo.AddTime.Value.ToString("yyyy/MM/dd") + " 23:59:59");
                userInfoIq = userInfoIq.Where(a => a.AddTime.Value.CompareTo(dateTimeStart) >= 0 && a.AddTime.Value.CompareTo(dateTimeEnd) < 0);
            }
            return userInfoIq;
        }
        #endregion
        
    }
}
